home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2006 May / PCWMAY06.iso / Software / Toolkit / Songbird 0.1 / Songbird_0_1_0.exe / components / sbIPlaylistReaderRSS.js < prev    next >
Encoding:
Text File  |  2006-02-08  |  13.1 KB  |  475 lines

  1. /*
  2.  //
  3. // BEGIN SONGBIRD GPL
  4. // 
  5. // This file is part of the Songbird web player.
  6. //
  7. // Copyright⌐ 2006 Pioneers of the Inevitable LLC
  8. // http://songbirdnest.com
  9. // 
  10. // This file may be licensed under the terms of of the
  11. // GNU General Public License Version 2 (the ôGPLö).
  12. // 
  13. // Software distributed under the License is distributed 
  14. // on an ôAS ISö basis, WITHOUT WARRANTY OF ANY KIND, either 
  15. // express or implied. See the GPL for the specific language 
  16. // governing rights and limitations.
  17. //
  18. // You should have received a copy of the GPL along with this 
  19. // program. If not, go to http://www.gnu.org/licenses/gpl.html
  20. // or write to the Free Software Foundation, Inc., 
  21. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  22. // 
  23. // END SONGBIRD GPL
  24. //
  25.  */
  26.  
  27. //
  28. // sbIPlaylistReader Object (RSS)
  29. //
  30.  
  31. const SONGBIRD_PLAYLISTRSS_CONTRACTID = "@songbird.org/Songbird/Playlist/Reader/RSS;1";
  32. const SONGBIRD_PLAYLISTRSS_CLASSNAME = "Songbird RSS Playlist Interface";
  33. const SONGBIRD_PLAYLISTRSS_CID = Components.ID("{E22A572D-BA5F-4e00-93B5-9C8DF3E28A41}");
  34. const SONGBIRD_PLAYLISTRSS_IID = Components.interfaces.sbIPlaylistReader;
  35.  
  36. function CPlaylistRSS()
  37. {
  38.   jsLoader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader);
  39.   jsLoader.loadSubScript( "chrome://rmp_demo/content/songbird_interfaces.js", this );
  40. }
  41.  
  42. /* I actually need a constructor in this case. */
  43. CPlaylistRSS.prototype.constructor = CPlaylistRSS;
  44.  
  45. /* the CPlaylistRSS class def */
  46. CPlaylistRSS.prototype = 
  47. {
  48.   originalURL: "",
  49.  
  50.   m_document: null,
  51.   m_playlistmgr: null,
  52.   m_playlist: null,
  53.   m_library: null,
  54.   m_query: null,
  55.   
  56.   m_guid: "",
  57.   m_table: "",
  58.   m_append: false,
  59.     
  60.   Read: function( strURL, strGUID, strDestTable, bAppendOrReplace, /* out */ errorCode )
  61.   {
  62.     try
  63.     {
  64.       errorCode.value = 0;
  65.  
  66.       var domParser = Components.classes["@mozilla.org/xmlextras/domparser;1"].createInstance(Components.interfaces.nsIDOMParser);
  67.       var pFileReader = (Components.classes["@mozilla.org/network/file-input-stream;1"]).createInstance(Components.interfaces.nsIFileInputStream);
  68.       var pFile = (Components.classes["@mozilla.org/file/local;1"]).createInstance(Components.interfaces.nsILocalFile);
  69.       var pURI = (Components.classes["@mozilla.org/network/simple-uri;1"]).createInstance(Components.interfaces.nsIURI);
  70.  
  71.       if ( domParser && pFile && pURI && pFileReader )
  72.       {
  73.         pURI.spec = strURL;
  74.         if ( pURI.scheme == "file" )
  75.         {
  76.           var cstrPathToPLS = pURI.path;
  77.           cstrPathToPLS = cstrPathToPLS.substr( 3, cstrPathToPLS.length );
  78.           pFile.initWithPath(cstrPathToPLS);
  79.           if ( pFile.isFile() )
  80.           {
  81.             pFileReader.init( pFile, /* PR_RDONLY */ 1, 0, /*nsIFileInputStream::CLOSE_ON_EOF*/ 0 );
  82.             var document = domParser.parseFromStream(pFileReader, null, pFileReader.available(), "application/xml");
  83.             pFileReader.close();
  84.             
  85.             if(document)
  86.             {
  87.               const MediaLibrary = new Components.Constructor("@songbird.org/Songbird/MediaLibrary;1", "sbIMediaLibrary");
  88.               const PlaylistManager = new Components.Constructor("@songbird.org/Songbird/PlaylistManager;1", "sbIPlaylistManager");
  89.  
  90.               this.m_guid = strGUID;
  91.               this.m_table = strDestTable;
  92.               this.m_append = bAppendOrReplace;
  93.               
  94.               this.m_query = new this.sbIDatabaseQuery();
  95.               this.m_query.SetAsyncQuery(true);
  96.               this.m_query.SetDatabaseGUID(strGUID);
  97.  
  98.               this.m_document = document;
  99.               this.m_library = new MediaLibrary();
  100.               this.m_playlistmgr = new PlaylistManager();
  101.               
  102.               this.m_library.SetQueryObject(this.m_query);
  103.               var playlist = this.m_playlistmgr.GetPlaylist(strDestTable, this.m_query);
  104.               
  105.               if(playlist)
  106.               {
  107.                 this.m_playlist = playlist;
  108.                 return this.ProcessXMLDocument(this.m_document);
  109.               }
  110.             }
  111.           }
  112.         }
  113.       }
  114.     }
  115.     catch ( err )
  116.     {
  117.       throw "CPlaylistRSS::Read - " + err;
  118.     }
  119.     
  120.     return false;
  121.   },
  122.   
  123.   Vote: function( strURL )
  124.   {
  125.     try
  126.     {
  127.       return 10000;
  128.     }
  129.     catch ( err )
  130.     {
  131.       throw "CPlaylistRSS::Vote - " + err;
  132.     }
  133.   },
  134.   
  135.   Name: function()
  136.   {
  137.     try
  138.     {
  139.       return "RSS Playlist"; // ????
  140.     }
  141.     catch ( err )
  142.     {
  143.       throw "CPlaylistRSS::Name - " + err;
  144.     }
  145.   },
  146.   
  147.   Description: function()
  148.   {
  149.     try
  150.     {
  151.       return "RSS Playlist"; // ????
  152.     }
  153.     catch ( err )
  154.     {
  155.       throw "CPlaylistRSS::Description - " + err;
  156.     }
  157.   },
  158.   
  159.   SupportedMIMETypes: function( /* out */ nMIMECount )
  160.   {
  161.     var retval = new Array;
  162.     nMIMECount.value = 0;
  163.     
  164.     try
  165.     {
  166.       retval.push( "text/xml" );
  167.       retval.push( "text/html" );
  168.       retval.push( "text/rss+xml" );
  169.       retval.push( "application/xml" );
  170.       
  171.       nMIMECount.value = retval.length;
  172.     }
  173.     catch ( err )
  174.     {
  175.       throw "CPlaylistRSS::SupportedMIMETypes - " + err;
  176.     }
  177.     return retval;
  178.   },
  179.   
  180.   SupportedFileExtensions: function( /* out */ nExtCount )
  181.   {
  182.     var retval = new Array;
  183.     nExtCount.value = 0;
  184.     
  185.     try
  186.     {
  187.       retval.push( "rss" );
  188.       retval.push( "xml" );
  189.       
  190.       nExtCount.value = retval.length;
  191.     }
  192.     catch ( err )
  193.     {
  194.       throw "CPlaylistRSS::SupportedFileExtensions - " + err;
  195.     }
  196.     
  197.     return retval;
  198.   },
  199.   
  200.   ProcessXMLDocument: function( xmlDocument )
  201.   {
  202.     var ret = false;
  203.     try
  204.     {
  205.       var document = xmlDocument.documentElement;
  206.       
  207.       if(document.tagName == "rss")
  208.       {
  209.         var rssVersion = document.getAttribute("version");
  210.         dump("CPlaylistRSS::ProcessXMLDocument - RSS Version: " + rssVersion + "\n");
  211.         
  212.         if(rssVersion[0] == "2")
  213.         {
  214.           ret = this.ProcessRSSFeed(document);
  215.         }
  216.       }
  217.     }
  218.     catch(err)
  219.     {
  220.       throw "CPlaylistRSS::ProcessXMLDocument - " + err;
  221.     }
  222.     
  223.     return ret;
  224.   },
  225.   
  226.   ProcessRSSFeed: function( xmlDocument )
  227.   {
  228.     try
  229.     {
  230.       var channels = xmlDocument.getElementsByTagName("channel");
  231.       var i = 0;
  232.       
  233.       for(; i < channels.length; i++)
  234.       {
  235.         var playlistTitle = "";
  236.         var playlistDescription = "";
  237.         
  238.         var channel = channels.item(i);
  239.         
  240.         var children = channel.childNodes;
  241.         var j = 0;
  242.         for(; j < children.length; j++)
  243.         {
  244.           var child = children.item(j);
  245.           
  246.           switch(child.nodeName)
  247.           {
  248.             case "title": this.m_playlist.SetReadableName(child.firstChild.data); break;
  249.             case "description": playlistDescription = ""; break;
  250.             case "item": this.ProcessRSSItem(child); break;
  251.           }
  252.         }
  253.         
  254.         var ret = this.m_query.Execute();
  255.         
  256.         return (ret == 0);
  257.       }
  258.     }
  259.     catch(err)
  260.     {
  261.       throw "CPlaylistRSS::ProcessXMLDocument - " + err;
  262.     }
  263.     
  264.     return false;
  265.   },
  266.   
  267.   ProcessRSSItem: function(xmlElement)
  268.   {
  269.     try
  270.     {
  271.       var url = "";
  272.       var artist = "";
  273.       var title = "";
  274.       var type = "";
  275.       var size = "";
  276.  
  277.       var i = 0;
  278.       var children = xmlElement.childNodes;
  279.       for(; i < children.length; i++)
  280.       {
  281.         var child = children.item(i);
  282.         
  283.         switch(child.nodeName)
  284.         {
  285.           case "title":
  286.           {
  287.             if(child.hasChildNodes() && child.firstChild.nodeType == 3)
  288.             {
  289.               title = child.firstChild.data;
  290.             }
  291.           }
  292.           break;
  293.  
  294.           case "itunes:author":
  295.           {
  296.             if(child.hasChildNodes() && child.firstChild.nodeType == 3)
  297.             {
  298.               artist = child.firstChild.data;
  299.             }
  300.           }
  301.           break;
  302.           
  303.           case "enclosure":
  304.           {
  305.             if(child.hasAttributes() && child.nodeType == 1)
  306.             {
  307.               url = child.getAttribute("url");
  308.               type = child.getAttribute("type");
  309.               size = child.getAttribute("length");
  310.             }
  311.           }
  312.           break;
  313.         }
  314.       }
  315.       
  316.       if(url != "" && this.IsMediaUrl(url))
  317.       {
  318.         var aMetaKeys = new Array("artist", "title", "content_type");
  319.         var aMetaValues = new Array( artist, title, type );
  320.  
  321.         var guid = this.m_library.AddMedia( url, aMetaKeys.length, aMetaKeys, aMetaValues.length, aMetaValues, this.m_append, true );
  322.         this.m_playlist.AddByGUID( guid, this.m_guid, -1, this.m_append, true );
  323.         
  324.         return true;
  325.       }
  326.     }
  327.     catch(err)
  328.     {
  329.       throw "CPlaylistRSS::ProcessRSSItem - " + err;
  330.     }
  331.   },
  332.   
  333.   IsMediaUrl: function( the_url )
  334.   {
  335.     if ( ( the_url.indexOf ) && 
  336.           (
  337.             // Protocols at the beginning
  338.             ( the_url.indexOf( "mms:" ) == 0 ) || 
  339.             ( the_url.indexOf( "rtsp:" ) == 0 ) || 
  340.             // File extensions at the end
  341.             ( the_url.indexOf( ".pls" ) != -1 ) || 
  342.             ( the_url.indexOf( ".m3u" ) == ( the_url.length - 4 ) ) || 
  343. //            ( the_url.indexOf( ".rm" ) == ( the_url.length - 3 ) ) || 
  344. //            ( the_url.indexOf( ".ram" ) == ( the_url.length - 4 ) ) || 
  345. //            ( the_url.indexOf( ".smil" ) == ( the_url.length - 5 ) ) || 
  346.             ( the_url.indexOf( ".mp3" ) == ( the_url.length - 4 ) ) ||
  347.             ( the_url.indexOf( ".m4a" ) == ( the_url.length - 4 ) ) ||
  348.             ( the_url.indexOf( ".ogg" ) == ( the_url.length - 4 ) ) ||
  349.             ( the_url.indexOf( ".wma" ) == ( the_url.length - 4 ) ) ||
  350.             ( the_url.indexOf( ".wmv" ) == ( the_url.length - 4 ) ) ||
  351.             ( the_url.indexOf( ".asx" ) == ( the_url.length - 4 ) ) ||
  352.             ( the_url.indexOf( ".asf" ) == ( the_url.length - 4 ) ) ||
  353.             ( the_url.indexOf( ".avi" ) == ( the_url.length - 4 ) ) ||
  354.             ( the_url.indexOf( ".mov" ) == ( the_url.length - 4 ) ) ||
  355.             ( the_url.indexOf( ".mp4" ) == ( the_url.length - 4 ) )
  356.           )
  357.         )
  358.     {
  359.       return true;
  360.     }
  361.     return false;
  362.   },
  363.   
  364.   ConvertUrlToDisplayName: function( url )
  365.   {
  366.     // Set the title display  
  367.     var the_value = "";
  368.     if ( url.lastIndexOf('/') != -1 )
  369.     {
  370.       the_value = url.substring( url.lastIndexOf('/') + 1, url.length );
  371.     }
  372.     else if ( url.lastIndexOf('\\') != -1 )
  373.     {
  374.       the_value = url.substring( url.lastIndexOf('\\') + 1, url.length );
  375.     }
  376.     else
  377.     {
  378.       the_value = url;
  379.     }
  380.     // Convert any %XX to space
  381.     var percent = the_value.indexOf('%');
  382.     if ( percent != -1 )
  383.     {
  384.       var remainder = the_value;
  385.       the_value = "";
  386.       while ( percent != -1 )
  387.       {
  388.         the_value += remainder.substring( 0, percent );
  389.         remainder = remainder.substring( percent + 3, url.length );
  390.         percent = remainder.indexOf('%');
  391.         the_value += " ";
  392.         if ( percent == -1 )
  393.         {
  394.           the_value += remainder;
  395.         }
  396.       }
  397.     }
  398.     if ( the_value.length == 0 )
  399.     {
  400.       the_value = url;
  401.     }
  402.     return the_value;
  403.   },
  404.  
  405.   QueryInterface: function(iid)
  406.   {
  407.       if (!iid.equals(Components.interfaces.nsISupports) &&
  408.           !iid.equals(SONGBIRD_PLAYLISTRSS_IID))
  409.           throw Components.results.NS_ERROR_NO_INTERFACE;
  410.       return this;
  411.   }
  412. }; //CPlaylistRSS
  413.  
  414. /**
  415.  * \class sbPlaylistRSSModule
  416.  * \brief 
  417.  */
  418. var sbPlaylistRSSModule = 
  419. {
  420.   registerSelf: function(compMgr, fileSpec, location, type)
  421.   {
  422.     compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  423.     compMgr.registerFactoryLocation(SONGBIRD_PLAYLISTRSS_CID, 
  424.                                     SONGBIRD_PLAYLISTRSS_CLASSNAME, 
  425.                                     SONGBIRD_PLAYLISTRSS_CONTRACTID, 
  426.                                     fileSpec, 
  427.                                     location,
  428.                                     type);
  429.   },
  430.  
  431.   getClassObject: function(compMgr, cid, iid) 
  432.   {
  433.     if(!cid.equals(SONGBIRD_PLAYLISTRSS_CID))
  434.         throw Components.results.NS_ERROR_NO_INTERFACE;
  435.  
  436.     if(!iid.equals(Components.interfaces.nsIFactory))
  437.         throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  438.  
  439.     return sbPlaylistRSSFactory;
  440.   },
  441.  
  442.   canUnload: function(compMgr)
  443.   { 
  444.     return true; 
  445.   }
  446. }; //sbPlaylistRSSModule
  447.  
  448. /**
  449.  * \class sbPlaylistHTMLFactory
  450.  * \brief 
  451.  */
  452. var sbPlaylistRSSFactory =
  453. {
  454.   createInstance: function(outer, iid)
  455.   {
  456.     if (outer != null)
  457.         throw Components.results.NS_ERROR_NO_AGGREGATION;
  458.  
  459.     if (!iid.equals(SONGBIRD_PLAYLISTRSS_IID) &&
  460.         !iid.equals(Components.interfaces.nsISupports))
  461.         throw Components.results.NS_ERROR_INVALID_ARG;
  462.  
  463.     return (new CPlaylistRSS()).QueryInterface(iid);
  464.   }
  465. }; //sbPlaylistRSSFactory
  466.  
  467. /**
  468.  * \function NSGetModule
  469.  * \brief 
  470.  */
  471. function NSGetModule(comMgr, fileSpec)
  472.   return sbPlaylistRSSModule;
  473. } //NSGetModule
  474.